#include "Game.h"
Game::Game()
{
}

Game::~Game()
{
}

void Game::Initialize()
{
	m_xDisplayManager = DisplayManager::GetInstance();
	m_xDisplayManager->Initialize();
	m_xWindow = DisplayManager::GetInstance()->GetRenderWindow();
	m_xAgentManager = AgentManager::GetInstance();
	m_xSpriteManager = SpriteManager::GetInstance();
	
	m_xInputHandler = InputHandler::GetInstance();
	m_xInputHandler->Initialize();

	m_xClock.restart();
	m_fDelta = m_xClock.getElapsedTime().asSeconds();
	srand(time(NULL));

	m_xFont.loadFromFile("Images/BebasNeue.otf");

	// Create the world grid
	CreateGrid();

	m_xAgentManager->Initialize(Grid);

	m_xWorldObjectManager = WorldObjectManager::GetInstance();
	m_xWorldObjectManager->Initialize(Grid);
	
	// Agents
	//for (int i = 0; i < 1; i++)
	//{
	//	m_xAgentManager->SpawnAnimal(Animals::Bunny);
	//	//m_xAgentManager->SpawnAnimal(Animals::Wolf);
	//	m_xAgentManager->SpawnAnimal(Animals::Bear);
	//}

	m_fKeyboardDelay = 0;

	// Player
	m_xPlayer = new Player();
	m_xPlayer->Initialize(Grid);
	m_xPlayer->SetCurrentNode(Grid[10][10]);
	m_xPlayer->SetPosition(Grid[10][10]->m_vPosition);
	m_xAgentManager->SetPlayer(m_xPlayer);

	// Buttons
	m_xWolfButton = new GUIButton();
	m_xWolfButton->Initialize("Spawn Wolf", sf::Vector2f(1000.0f, 500.0f), m_xFont);
	m_xBunnyButton = new GUIButton();
	m_xBunnyButton->Initialize("Spawn Bunny", sf::Vector2f(1000.0f, 550.0f), m_xFont);
	m_xBearButton = new GUIButton();
	m_xBearButton->Initialize("Spawn Bear", sf::Vector2f(1000.0f, 600.0f), m_xFont);
}

void Game::Update()
{
	while (m_xWindow->isOpen())
	{
		while (m_xWindow->pollEvent(m_xEvent))
		{
			if (m_xEvent.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Q))
				m_xWindow->close();
		}

		m_fDelta = m_xClock.getElapsedTime().asSeconds();
		m_xClock.restart();

		// --- Gameplay --- //

		m_xPlayer->Update(m_fDelta);
		m_xAgentManager->Update(m_fDelta);
		m_xWorldObjectManager->Update(m_fDelta);
		m_xInputHandler->Update();
		
		m_xWolfButton->Update();
		m_xBunnyButton->Update();
		m_xBearButton->Update();

		if (m_xBunnyButton->IsPressed(m_xInputHandler->GetMousePosition()))
		{
			m_xAgentManager->SpawnAnimal(Animals::Bunny);
		}

		if (m_xWolfButton->IsPressed(m_xInputHandler->GetMousePosition()))
		{
			m_xAgentManager->SpawnAnimal(Animals::Wolf);
		}

		if (m_xBearButton->IsPressed(m_xInputHandler->GetMousePosition()))
		{
			m_xAgentManager->SpawnAnimal(Animals::Bear);
		}

		// --- Gameplay --- //

		m_xDisplayManager->Draw();
	}
}

void Game::Cleanup()
{
	m_xAgentManager->Cleanup();
	m_xAgentManager->Destroy();

	m_xWorldObjectManager->Cleanup();
	m_xWorldObjectManager->Destroy();

	m_xDisplayManager->Cleanup();
	m_xDisplayManager->Destroy();

	m_xSpriteManager->Destroy();

	for (int x = 0; x < Grid.size(); x++)
	{
		for (int y = 0; y < Grid[x].size(); y++)
		{
			//Grid[x][y]->Cleanup();
			delete Grid[x][y];
			Grid[x][y] = nullptr;
		}
		Grid[x].clear();
	}
	Grid.clear();
}

void Game::CreateGrid()
{
	int gridSize = 30;

	float nodeThickness = 1.0f;
	sf::Vector2f nodeSize(30.0f, 30.0f);
	sf::Vector2f nodePosition((nodeSize.x * 0.5f) + nodeThickness, (nodeSize.y * 0.5f) + nodeThickness);

	float space = 2.0f;
	sf::Vector2f nodeSpace(nodeSize.x + space, nodeSize.y + space);

	// Add 5 rows to the vector
	// x x x x x
	for (int i = 0; i < gridSize; i++)
	{
		Grid.push_back(vector<Node*>());
	}

	// Add colums to all the rows
	//   0 1 2 3 4
	// 0 x x x x x
	// 1 x x x x x
	// 2 x x x x x
	// 3 x x x x x
	// 4 x x x x x

	Node* tempNode;
	for (int j = 0; j < gridSize; j++)
	{
		for (int i = 0; i < Grid.size(); i++)
		{
			tempNode = new Node();
			Grid[i].push_back(tempNode);
		}
	}

	// Rectangle shape, text coordinates and coordinate ID
	//sf::Text* pText;
	sf::RectangleShape* rectShape;
	sf::Vector2i pCount(0, 0);
	for (int x = 0; x < Grid.size(); x++)
	{
		for (int y = 0; y < Grid[x].size(); y++)
		{
			// ID
			pCount.y = y;
			Grid[x][y]->m_vID = pCount;

			// Connections - 4 Empty nodes
			for (int i = 0; i < 8; i++)
			{
				Grid[x][y]->m_xAdjacentNodes.push_back(NULL);
			}

			// If there is a node above this node, add it
			if (y != 0)
				Grid[x][y]->m_xAdjacentNodes[0] = Grid[x][(y - 1)];
			// If there is a node below this node, add it
			if (y != Grid.size() - 1)
				Grid[x][y]->m_xAdjacentNodes[1] = Grid[x][(y + 1)];
			
			// If there is a node to the left of this node, add it
			if (x != 0)
				Grid[x][y]->m_xAdjacentNodes[2] = Grid[(x - 1)][y];
			// If there is a node to the right of this node, add it
			if (x != Grid.size() - 1)
				Grid[x][y]->m_xAdjacentNodes[3] = Grid[(x + 1)][y];
			
			// If there is a node to the NE, add it 
			if ((x != Grid.size() - 1) && (y != 0))
				Grid[x][y]->m_xAdjacentNodes[4] = Grid[(x + 1)][(y - 1)];
			// If there is a node to the NW, add it
			if ((x != 0) && (y != 0))
				Grid[x][y]->m_xAdjacentNodes[7] = Grid[(x - 1)][(y - 1)];

			// If there is a node to the SW, add it 
			if ((x != 0) && (y != Grid.size() - 1))
				Grid[x][y]->m_xAdjacentNodes[6] = Grid[(x - 1)][(y + 1)];
			// If there is a node to the SE, add it
			if ((x != Grid.size() - 1) && (y != Grid.size() - 1))
				Grid[x][y]->m_xAdjacentNodes[5] = Grid[(x + 1)][(y + 1)];


			// Positon
			Grid[x][y]->m_vPosition = nodePosition;
			nodePosition.y += nodeSpace.y;

			// Rectangle
			rectShape = new sf::RectangleShape();
			rectShape->setSize(nodeSize);
			rectShape->setFillColor(sf::Color::Transparent);
			rectShape->setOutlineColor(sf::Color(255, 255, 255, 100));
			rectShape->setOutlineThickness(nodeThickness);
			rectShape->setPosition(Grid[x][y]->m_vPosition);
			rectShape->setOrigin(rectShape->getSize().x / 2, rectShape->getSize().y / 2);
			m_xDisplayManager->AddDrawable(rectShape, 2);
			Grid[x][y]->m_xRect = rectShape;

			// Add ground sprite
			Grid[x][y]->LoadGroundTile();

			// Make some nodes blocked
			Grid[x][y]->m_bBlocked = false; 
			int makeblock = rand() % 5;
			bool hasAdjacent = false;
			if (makeblock == 1)
			{
				for (int i = 0; i < Grid[x][y]->m_xAdjacentNodes.size(); i++)
				{
					if (Grid[x][y]->m_xAdjacentNodes[i] == nullptr || Grid[x][y]->m_xAdjacentNodes[i]->m_bBlocked)
					{
						hasAdjacent = true;
					}
				}

				if (!hasAdjacent)
				{
					Grid[x][y]->m_bBlocked = true;
					int treeType = rand() % 10;
					switch (treeType)
					{
						case 0:
							Grid[x][y]->LoadObjectSprite(Node::TreeType1);
							break;
						case 1:
							Grid[x][y]->LoadObjectSprite(Node::TreeType2);
							break;
						case 2:
							Grid[x][y]->LoadObjectSprite(Node::RockType1);
							break;
						case 3:
							Grid[x][y]->LoadObjectSprite(Node::RockType2);
							break;
						default:
							Grid[x][y]->LoadObjectSprite(Node::TreeType1);
							break;
					}
				}
			}
			else
			{
				Grid[x][y]->m_xObjectSprite = nullptr;
			}
		}

		pCount.x = (x + 1);
		nodePosition.x += nodeSpace.x;
		nodePosition.y = (nodeSize.y * 0.5f) + nodeThickness;


	}

	//int RandX = rand() % 30;
	//int RandY = rand() % 30;
	//int RandX2 = rand() % 30;
	//int RandY2 = rand() % 30;
	//Grid[RandX][RandY]->m_xRect->setFillColor(sf::Color::Magenta);
	//
	//Grid[RandY2][RandX2]->m_xRect->setFillColor(sf::Color::Green);
	//std::cout << RandY2 << " " << RandX2 << "\n";
	
	/*aStar.Setup(Grid[RandX][RandY], Grid[RandY2][RandX2]);*/
}
